#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>

#include "../comm/log.hpp"
#include "../comm/util.hpp"

namespace ns_runner{
    using namespace ns_log;
    using namespace ns_util;
    class runner{
        public:
        runner(){}
        ~runner(){}
        //提供设置进程占用资源大小的接口
        static void SetProcLimit(int _cpu_limit, int _mem_limit)
        {
            // 设置CPU时长
            struct rlimit cpu_rlimit;
            cpu_rlimit.rlim_max = RLIM_INFINITY;
            cpu_rlimit.rlim_cur = _cpu_limit;
            setrlimit(RLIMIT_CPU, &cpu_rlimit);

            // 设置内存大小
            struct rlimit mem_rlimit;
            mem_rlimit.rlim_max = RLIM_INFINITY;
            mem_rlimit.rlim_cur = _mem_limit * 1024; //转化成为KB
            setrlimit(RLIMIT_AS, &mem_rlimit);
        }
        static int run(const std::string&file_name,int cpu_limit, int mem_limit){
            std::string _exe = PathUtil::Exe(file_name);
            int _stdin=open((PathUtil::Stdin(file_name)).c_str(),O_CREAT|O_RDONLY,0644);
            int _stdout=open((PathUtil::Stdout(file_name)).c_str(),O_CREAT|O_WRONLY,0644);
            int _stderr=open((PathUtil::Stderr(file_name)).c_str(),O_CREAT|O_WRONLY,0644);
            if(_stdin<0||_stdout<0||_stderr<0)
            {
                LOG(ERROR)<<"运行时文件打开失败";
                return -1;//文件打开失败;
            }
            pid_t pid=fork();
            if(pid<0)
            {
                LOG(ERROR)<<"运行时子进程创建失败";
                return -2;
            }
            else if(pid==0)
            {
                dup2(_stdin,0);
                dup2(_stdout,1);
                dup2(_stderr,2);
                SetProcLimit(cpu_limit, mem_limit);
                execl(_exe.c_str()/*我要执行谁*/, _exe.c_str()/*我想在命令行上如何执行该程序*/, nullptr);
                exit(1);
            }
            else{
                close(_stdin);
                close(_stdout);
                close(_stderr);
                int status = 0;
                waitpid(pid, &status, 0);
                // 程序运行异常，一定是因为因为收到了信号！
                return status &0x7F;
            }
        }
    };
}
